// @before-stub-for-debug-begin
#include <vector>
#include <string>

using namespace std;
// @before-stub-for-debug-end

/*
 * @lc app=leetcode.cn id=227 lang=cpp
 *
 * [227] 基本计算器 II
 *
 * https://leetcode-cn.com/problems/basic-calculator-ii/description/
 *
 * algorithms
 * Medium (43.80%)
 * Likes:    550
 * Dislikes: 0
 * Total Accepted:    106.6K
 * Total Submissions: 243.2K
 * Testcase Example:  '"3+2*2"'
 *
 * 给你一个字符串表达式 s ，请你实现一个基本计算器来计算并返回它的值。
 *
 * 整数除法仅保留整数部分。
 *
 * 你可以假设给定的表达式总是有效的。所有中间结果将在 [-2^31, 2^31 - 1] 的范围内。
 *
 * 注意：不允许使用任何将字符串作为数学表达式计算的内置函数，比如 eval() 。
 *
 *
 *
 * 示例 1：
 *
 *
 * 输入：s = "3+2*2"
 * 输出：7
 *
 *
 * 示例 2：
 *
 *
 * 输入：s = " 3/2 "
 * 输出：1
 *
 *
 * 示例 3：
 *
 *
 * 输入：s = " 3+5 / 2 "
 * 输出：5
 *
 *
 *
 *
 * 提示：
 *
 *
 * 1 <= s.length <= 3 * 10^5
 * s 由整数和算符 ('+', '-', '*', '/') 组成，中间由一些空格隔开
 * s 表示一个 有效表达式
 * 表达式中的所有整数都是非负整数，且在范围 [0, 2^31 - 1] 内
 * 题目数据保证答案是一个 32-bit 整数
 *
 *
 */

// @lc code=start
#include <string>
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
class Solution
{
public:
    /* int calculate(string s)
    {
        stack<long> nums;
        stack<char> operas;
        int status = 0;
        int minus = 0;
        long a1 = 0, a2 = 0, ret = 0;
        auto it1 = s.begin();
        while (it1 != s.end())
        {
            if (*it1 == ' ')
            {
                s.erase(it1);
            }
            else
            {
                it1++;
            }
        }
        auto it = s.begin();
        while (it != s.end())
        {
            if (*it == '+')
            {
                operas.push(*it);
                it++;
            }
            else if (*it == '-')
            {
                minus = 1;
                it++;
            }
            else if (*it == '*' || *it == '/')
            {
                operas.push(*it);
                status = 1;
                it++;
            }
            else
            {
                long cur_num = 0;
                // 将从i位置开始后面的连续数字整体取出，加入nums
                while (it != s.end() && isdigit(*it))
                {
                    cur_num = cur_num * 10 + (*it - '0');
                    it++;
                }
                if (minus == 2)
                {
                    cur_num = -cur_num;
                    minus = 0;
                }
                nums.push(cur_num);
            }
            if (status == 2 && nums.size() >= 2)
            {
                a1 = nums.top();
                nums.pop();
                a2 = nums.top();
                nums.pop();
                if (operas.top() == '*')
                {
                    operas.pop();
                    ret = a1 * a2;
                    nums.push(ret);
                }
                else
                {
                    operas.pop();
                    ret = a2 / a1;
                    nums.push(ret);
                }
                status = 0;
            }
            if (status == 1)
            {
                status++;
            }
            if (minus == 1)
            {
                minus++;
            }
        }
        while (nums.size() >= 2)
        {
            a1 = nums.top();
            nums.pop();
            a2 = nums.top();
            nums.pop();
            ret = a1 + a2;
            nums.push(ret);
        }
        return nums.top();
    } */
    int calculate(string s)
    {
        vector<int> stk;
        char preSign = '+';
        int num = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i)
        {
            if (isdigit(s[i]))
            {
                num = num * 10 + int(s[i] - '0');
            }
            if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1)
            {
                switch (preSign)
                {
                case '+':
                    stk.push_back(num);
                    break;
                case '-':
                    stk.push_back(-num);
                    break;
                case '*':
                    stk.back() *= num;
                    break;
                default:
                    stk.back() /= num;
                }
                preSign = s[i];
                num = 0;
            }
        }
        return accumulate(stk.begin(), stk.end(), 0);
    }
};
// @lc code=end
